package drds.binlog.event;

import drds.binlog.LogByteBlock;
import drds.binlog.LogEvent;

/**
 * Class representing an incident, an occurance out of the ordinary, that
 * happened on the master. The event is used to inform the slave that something
 * out of the ordinary happened on the master that might cause the database to
 * be in an inconsistent state.
 * <table id="IncidentFormat">
 * <caption>Incident event format</caption>
 * <tr>
 * <th>Symbol</th>
 * <th>Format</th>
 * <th>Description</th>
 * </tr>
 * <tr>
 * <td>INCIDENT</td>
 * <td align="right">2</td>
 * <td>Incident number as an unsigned integer</td>
 * </tr>
 * <tr>
 * <td>MSGLEN</td>
 * <td align="right">1</td>
 * <td>Message length as an unsigned integer</td>
 * </tr>
 * <tr>
 * <td>MESSAGE</td>
 * <td align="right">MSGLEN</td>
 * <td>The message, if present. Not null terminated.</td>
 * </tr>
 * </table>
 *
 * @author <a href="mailto:changyuan.lh@taobao.com">Changyuan.lh</a>
 * @version 1.0
 */
public final class IncidentLogEvent extends LogEvent
{

    public static final int INCIDENT_NONE = 0;

    /**
     * There are possibly lost events in the replication stream
     */
    public static final int INCIDENT_LOST_EVENTS = 1;

    /**
     * Shall be last event of the enumeration
     */
    public static final int INCIDENT_COUNT = 2;

    private final int incident;
    private final String message;

    public IncidentLogEvent(LogHeader logHeader, LogByteBlock logByteBlock, FormatDescriptionLogEvent formatDescriptionLogEvent)
    {
        super(logHeader);

        final int commonHeaderLength = formatDescriptionLogEvent.commonHeaderLength;
        final int postHeaderLength = formatDescriptionLogEvent.postHeaderLengths[logHeader.type - 1];

        logByteBlock.index(commonHeaderLength);
        final int incidentNumber = logByteBlock.getUint16BasedOnIndex();
        if (incidentNumber >= INCIDENT_COUNT || incidentNumber <= INCIDENT_NONE)
        {
            // If the incident is not recognized, this binlog event is
            // invalid. If we set incident_number to INCIDENT_NONE, the
            // invalidity will be detected by is_valid().
            incident = INCIDENT_NONE;
            message = null;
            return;
        }
        incident = incidentNumber;

        logByteBlock.index(commonHeaderLength + postHeaderLength);
        message = logByteBlock.getString();
    }

    public final int getIncident()
    {
        return incident;
    }

    public final String getMessage()
    {
        return message;
    }
}
